package bean.control;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.servlet.http.HttpSession;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import util.Crypto;
import util.Email;
import bean.entity.PersonBean;
import bean.entity.UserBean;
import bean.util.Authorization;
import bean.view.View;
import eao.EaoPerson;
import eao.EaoUser;
import eao.EaoUserPicture;
import eao.EaoUserSocialNetwork;
import entity.Person;
import entity.SocialNetwork;
import entity.User;
import entity.UserPicture;
import entity.UserSocialNetwork;
import entity.UserType;

@ManagedBean(name="userc")
@ViewScoped
public class UserControl implements Serializable {
	private static final long serialVersionUID = -1626847931067187536L;

	@EJB EaoUser eaoUser;
	@EJB EaoPerson eaoPerson;
	@EJB EaoUserPicture eaoUserPicture;
	@EJB EaoUserSocialNetwork eaoUserSocialNetwork;
	
	// Entities
	private User user;
	private Person person;

	// Bean Entities 
	@ManagedProperty("#{userBean}")
	private UserBean userb;
	
	@ManagedProperty("#{personBean}")
	private PersonBean personb;

	private View view;	
	
	// Variables
	private String code; 
	
	private boolean uploadImage;

	@NotNull(message = "6 dígitos no mínimo")
	@Size(min = 6, max = 128, message = "6 dígitos no mínimo")
	private String password;
	
	@NotNull(message = "6 dígitos no mínimo")
	@Size(min = 6, max = 128, message = "6 dígitos no mínimo")
	private String passwordOld;
	
	@PostConstruct
	public void init(){
		view = new View();
	}

	private void registerUser(Integer idUserType, String userType){
		userb.getUser().setPassword(Crypto.encrypt(userb.getUser().getPassword()));
		userb.getUser().setUserType(new UserType( idUserType, userType));
		userb.getUser().setReputation(0);

		try {
			eaoUser.create(userb.getUser());
		} catch (Exception e) {
			view.errorMessage("ocorreu um erro, por favor tente novamente");
			e.printStackTrace();
		}
	}
	
	public void registerPerson(){
		try {
			registerUser(new Integer(70), "person");
			
			personb.getPerson().setIdUser(userb.getUser().getId());
			personb.getPerson().setUser(userb.getUser());

			eaoPerson.create(personb.getPerson());

			view.successMessage("Cadastro efetuado com sucesso!");
		} catch (Exception e) {
			if (e.getMessage().contains("Duplicate")){
				view.errorMessage("Já existe um usuário com este e-mail, por favor informe outro e-mail.");
			}else{
				view.errorMessage("ocorreu um erro, por favor tente novamente");
				e.printStackTrace();
			}
		}
	}
	
	public void updatePerson(){
		this.checkSocialNetworks();
		
		eaoUser.update(userb.getUser());
		eaoPerson.update(personb.getPerson());
		
		view.successMessage("Dados atualizados com sucesso!");
	}
	
	// check if the other optional field from the user are filled correctly
	private void checkSocialNetworks(){
		eaoUserSocialNetwork.deleteAllFromUser(userb.getUser().getId());
		userb.getUser().getUserSocialNetworks().clear();
		
		if (userb.getFacebook() != null && !userb.getFacebook().isEmpty())
			userb.getUser().getUserSocialNetworks().add(new UserSocialNetwork(userb.getFacebook(), new SocialNetwork(new Integer(1), "Facebook"), userb.getUser()));
			
		if (userb.getGooglePlus() != null && !userb.getGooglePlus().isEmpty())
			userb.getUser().getUserSocialNetworks().add(new UserSocialNetwork(userb.getGooglePlus(), new SocialNetwork(new Integer(2), "Google+"), userb.getUser()));
			
		if (userb.getLink() != null && !userb.getLink().isEmpty())
			userb.getUser().getUserSocialNetworks().add(new UserSocialNetwork(userb.getLink(), new SocialNetwork(new Integer(3), "Link"), userb.getUser()));
			
		if (userb.getTwitter() != null && !userb.getTwitter().isEmpty())
			userb.getUser().getUserSocialNetworks().add(new UserSocialNetwork(userb.getTwitter(), new SocialNetwork(new Integer(4), "Twitter"), userb.getUser()));
			
		if (userb.getWebsite() != null && !userb.getWebsite().isEmpty())
			userb.getUser().getUserSocialNetworks().add(new UserSocialNetwork(userb.getWebsite(), new SocialNetwork(new Integer(5), "Website"), userb.getUser()));
	}
	
	public String login(){
		try{
			User u = eaoUser.findByEmail(userb.getUser().getEmail());
			
			if (u != null && Crypto.check(userb.getUser().getPassword(), u.getPassword())){
				
				userb.setUser(u);
				
				for (UserSocialNetwork us : userb.getUser().getUserSocialNetworks()){
					
					if (us.getSocialNetwork().getName().equals("Facebook")){
						userb.setFacebook(us.getLink());

					}else if (us.getSocialNetwork().getName().equals("Google+")){
						userb.setGooglePlus(us.getLink());
						
					}else if (us.getSocialNetwork().getName().equals("Link")){
						userb.setLink(us.getLink());
						
					}else if (us.getSocialNetwork().getName().equals("Twitter")){
						userb.setTwitter(us.getLink());
						
					}else if (us.getSocialNetwork().getName().equals("Website")){
						userb.setWebsite(us.getLink());
					}
				}
				
				personb.setPerson(u.getPerson());
				
				Authorization authorization = new Authorization();
				authorization.setLogged(true);
				
				HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false); 
				session.setAttribute("authorization", authorization);
				
				return "/user/home.xhtml?faces-redirect=true";
			}else{
				view.errorMessage("email e/ou senha incorretos");
				return "";
			}
		}catch(Exception e){
			view.errorMessage("ocorreu um erro, por favor, tente novamente");
			return "";
		}
			
	}

	public String logout() {
	        FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
	        return "/index.xhtml?faces-redirect=true";
    }

	public void updatePassword(){
		if (Crypto.check(passwordOld, userb.getUser().getPassword())){
			userb.getUser().setPassword(Crypto.encrypt(password));
			eaoUser.update(userb.getUser());
			view.successMessage("Senha atualizada com sucesso!");
		}else{
			view.errorMessage("Senha atual incorreta!");
		}
	}
	
	public void forgotPassword(){
		String url = "localhost:8080";
		String page = "http://"+ url +"/SuaParte/system/user/password/recover-password.xhtml";
			
		user = eaoUser.findByEmail( userb.getUser().getEmail() );
		
		if (user != null){
			Email email = new Email();
			String code = Crypto.encrypt(userb.getUser().getEmail());
			
			String message = "Olá Valter, <br/><br/> " +
                    "Você solicitou recentemente a redefinição de sua senha do Sua Parte.<br/>" +
                    "Para concluir a solicitação, " +
                    "<a href=\'http://localhost:8080/SuaParte/system/user/password/recover-password.xhtml?code="+code+"'>acesse este link</a><br/> " +
                    "Como alternativa, " +
                    "<a href='http://localhost:8080/SuaParte/system/user/password/recover-password.xhtml'>acesse</a>" + 
                    " e tentar novamente a solicitação de uma nova senha. <br/> " +
                    "Observe: Para sua proteção, este e-mail foi enviado a todos os endereços de e-mail associados a sua conta do Sua Parte. <br/> <br/>" +
                    "Não solicitou esta alteração? Se você não solicitou uma nova senha, por favor ignore este e-mail. <br/><br/><br/>" +
                    "Obrigada, <br/>" +
                    "A equipe do Sua Parte";
					
			try {
				email.simpleEmail(user.getEmail(), "Sua Parte : Recuperação de senha", message);
				view.successMessage("E-mail de recuperação enviado com sucesso!");
			} catch (AddressException e) {
				view.errorMessage("Erro ao tentar enviar o email de recuperação de conta, por favor, tente novamente.");
				e.printStackTrace();
			} catch (MessagingException e) {
				view.errorMessage("Erro ao tentar enviar o email de recuperação de conta, por favor, tente novamente.");
				e.printStackTrace();
			}
		}else{
			view.errorMessage("Este e-mail não esta associado a nenhum usuário, tente novamente.");
		}
		
	}
	
	public void recoverPassword(){
		if (Crypto.check(userb.getUser().getEmail(), code)){
			user = eaoUser.findByEmail(userb.getUser().getEmail());
			user.setPassword(Crypto.encrypt(password));
			
			eaoUser.update(user);
			view.successMessage("Senha nova atualizada com sucesso!");
		}else{
			view.successMessage("Ocorreu um erro ao tentar salvar sua nova senha. Por favor tente novamente.");
		}
	}
	
	public void showUploadImage(){
		uploadImage = true;
	}

	// Getter's and Setter's
	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public UserBean getUserb() {
		return userb;
	}

	public void setUserb(UserBean userb) {
		this.userb = userb;
	}

	public PersonBean getPersonb() {
		return personb;
	}

	public void setPersonb(PersonBean personb) {
		this.personb = personb;
	}

	public View getView() {
		return view;
	}

	public void setView(View view) {
		this.view = view;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public boolean isUploadImage() {
		return uploadImage;
	}

	public void setUploadImage(boolean uploadImage) {
		this.uploadImage = uploadImage;
	}

	public String getPasswordOld() {
		return passwordOld;
	}

	public void setPasswordOld(String passwordOld) {
		this.passwordOld = passwordOld;
	}


	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}
	
	
}
